#ifndef __FI__PLUGIN__H__
#define __FI__PLUGIN__H__

#include <iostream>
#include <assert.h>
#include "Core/Map.hpp"
#include "IModule.h"
#include "IPluginManager.h"

#define REGISTER_MODULE(pManager, classBaseName, className)  \
	assert((TIsDerived<classBaseName, IModule>::Result));	\
	assert((TIsDerived<className, classBaseName>::Result));	\
	IModule* pRegisterModule##className= new className(pManager); \
    pRegisterModule##className->strName = (#className); \
    pManager->AddModule( #classBaseName, pRegisterModule##className );\
    AddElement( #classBaseName, pRegisterModule##className );

#define REGISTER_TEST_MODULE(pManager, classBaseName, className)  \
	assert((TIsDerived<classBaseName, IModule>::Result));	\
	assert((TIsDerived<className, IModule>::Result));	\
	IModule* pRegisterModule##className= new className(pManager); \
    pRegisterModule##className->strName = (#className); \
    pManager->AddTestModule( #classBaseName, pRegisterModule##className );

#define UNREGISTER_MODULE(pManager, classBaseName, className) \
    IModule* pUnRegisterModule##className = dynamic_cast<IModule*>( pManager->FindModule( #classBaseName )); \
	pManager->RemoveModule( #classBaseName ); \
    RemoveElement( #classBaseName ); \
    delete pUnRegisterModule##className;

#define UNREGISTER_TEST_MODULE(pManager, classBaseName, className) \
    IModule* pUnRegisterModule##className = dynamic_cast<IModule*>( pManager->FindtESTModule( #classBaseName )); \
	pManager->RemoveTestModule( #classBaseName ); \
    delete pUnRegisterModule##className;

#define CREATE_PLUGIN(pManager, className)  \
	if(true){\
		IPlugin* prev = pManager->GetCurrentPlugin(); \
		IPlugin* pCreatePlugin##className = new className(pManager); \
		pCreatePlugin##className->strName = #className; \
		pManager->SetCurrentPlugin(pCreatePlugin##className); \
		pManager->Registered( pCreatePlugin##className ); \
		pManager->SetCurrentPlugin(prev);\
	}

	

#define DESTROY_PLUGIN(pManager, className) pManager->UnRegistered( pManager->FindPlugin((#className)) );

#define DECLARE_MODULE_NAME(className)		\
	public:\
		static std::string& GetModuleName(void)	\
		{\
			static std::string moduleName = #className;	\
			return moduleName;	\
		}

/*
#define REGISTER_COMPONENT(pManager, className)  NFIComponent* pRegisterComponent##className= new className(pManager); \
    pRegisterComponent##className->strName = (#className); \
    pManager->AddComponent( (#className), pRegisterComponent##className );

#define UNREGISTER_COMPONENT(pManager, className) NFIComponent* pRegisterComponent##className =  \
        dynamic_cast<NFIComponent*>( pManager->FindComponent( (#className) ) ); pManager->RemoveComponent( (#className) ); delete pRegisterComponent##className;
*/

namespace FragrantGrass
{
	class IPluginManager;

	class IPlugin : public IModule,
		public Map<std::string, IModule>
	{

	public:
		IPlugin()
		{
		}
		virtual ~IPlugin()
		{
		}

		virtual const int GetPluginVersion() = 0;

		virtual const std::string GetPluginName() = 0;

		virtual void Install() = 0;

		virtual bool Awake()
		{
			IModule* pModule = First();
			while (pModule)
			{
				m_pPluginManager->SetCurrenModule(pModule);

				bool bRet = pModule->Awake();
				if (!bRet)
				{
					std::cout << pModule->strName << std::endl;
					assert(0);
				}

				pModule = Next();
			}
			return true;
		}

		virtual bool Init()
		{
			IModule* pModule = First();
			while (pModule)
			{
				m_pPluginManager->SetCurrenModule(pModule);
				bool bRet = pModule->Init();
				if (!bRet)
				{
					std::cout << pModule->strName << std::endl;
					assert(0);
				}

				pModule = Next();
			}
			return true;
		}

		virtual bool AfterInit()
		{
			IModule* pModule = First();
			while (pModule)
			{
				m_pPluginManager->SetCurrenModule(pModule);
				bool bRet = pModule->AfterInit();
				if (!bRet)
				{
					std::cout << pModule->strName << std::endl;
					assert(0);
				}

				pModule = Next();
			}
			return true;
		}

		virtual bool CheckConfig()
		{
			IModule* pModule = First();
			while (pModule)
			{
				m_pPluginManager->SetCurrenModule(pModule);
				pModule->CheckConfig();

				pModule = Next();
			}

			return true;
		}

		virtual bool ReadyExecute()
		{
			IModule* pModule = First();
			while (pModule)
			{
				m_pPluginManager->SetCurrenModule(pModule);
				pModule->ReadyExecute();

				pModule = Next();
			}

			return true;
		}

		virtual bool Execute()
		{
			IModule* pModule = First();
			while (pModule)
			{
				m_pPluginManager->SetCurrenModule(pModule);
				pModule->Execute();

				pModule = Next();
			}

			return true;
		}

		virtual bool BeforeShut()
		{
			IModule* pModule = First();
			while (pModule)
			{
				m_pPluginManager->SetCurrenModule(pModule);
				pModule->BeforeShut();

				pModule = Next();
			}
			return true;
		}

		virtual bool Shut()
		{
			IModule* pModule = First();
			while (pModule)
			{
				m_pPluginManager->SetCurrenModule(pModule);
				pModule->Shut();

				pModule = Next();
			}

			return true;
		}

		virtual bool Finalize()
		{
			IModule* pModule = First();
			while (pModule)
			{
				m_pPluginManager->SetCurrenModule(pModule);
				pModule->Finalize();

				pModule = Next();
			}

			return true;
		}

		virtual bool OnReloadPlugin()
		{
			IModule* pModule = First();
			while (pModule)
			{
				m_pPluginManager->SetCurrenModule(pModule);
				pModule->OnReloadPlugin();

				pModule = Next();
			}

			return true;
		}
		virtual void Uninstall() = 0;
	};
}

#endif//__FI__PLUGIN__H__